<?php
/*
    *   redis 集合
    *
    * */

namespace App\Common;

use Illuminate\Support\Facades\Redis;
use GuzzleHttp\Client;
use App\Models\OrderRefund;
use Illuminate\Support\Facades\Log;

class WxMiniAppPay
{

    /**
     *
     */
    public function __construct()
    {
        $this->appid = 'wx1a09c081346adba2';
        $this->mchid = '1679193843';
        $this->corpId = 'wwb1d4989c6e6315a8';
        $this->corpSecret = 'xZuFCO4yADiGAFVxgCLPvnGJAbLaW4CjBS-x9b-34FQ';
    }

    /**调用微信支付
     * @param $order //订单信息
     * @param $user //用户信息
     * @param $pay_price //支付金额
     * @return void
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function doPay($order, $user, $pay_price)
    {
        !env('USE_WECHAT_PAY') && throwError('不支持使用微信支付');
        $goods_detail = [];
        foreach ($order->orderGoods as &$goods) {
            $goods_detail[] = [
                'merchant_goods_id' => $goods->goods_id,
                'unit_price' => (int)($goods->goods_price * 100),
                'quantity' => $goods->total_num
            ];
        }
        $access_token = $this->getAccessToken();
        if (!$access_token) {
            throwError('获取access_token失败');
        }
        $url = 'https://qyapi.weixin.qq.com/cgi-bin/miniapppay/create_order?access_token=' . $access_token;
        $payData = [
            'appid' => $this->appid,//二级商户申请的公众号或移动应用appid
            'mchid' => '1679193843',//二级商户号，由企业微信生成并下发。
            'out_trade_no' => $order->order_no,
            'description' => '商品下单',
            'amount' => [
                'total' => (int)($pay_price * 100),
                'currency' => 'CNY',
            ],
            'payer' => [
                'openid' => $user->open_id
            ],
            'detail' => [
                'goods_detail' => $goods_detail,
            ],
            'scene_info' => [
                'payer_client_ip' => (string)request()->ip(),
                'store_info' => [
                    'id' => 'storeHz001'
                ]
            ]
        ];
        $client = new Client();
        $response = $client->post($url, [
            'headers' => ['Content-Type' => 'application/json'],
            'body' => json_encode($payData)
        ]);
        $payData = json_decode($response->getBody(), true);
        if (isset($payData['errcode']) && $payData['errcode'] == 0) {
            if (isset($payData['prepay_id']) && $payData['prepay_id']) {
                //支付请求数据
                $parameters = array(
                    'appid' => 'wx1a09c081346adba2', //小程序ID
                    'timestamp' => (string)time(), //时间戳
                    'nonce' => $this->getNonceStr(), //随机串
                    'prepay_id' => $payData['prepay_id'], //数据包
                    'sign_type' => 'RSA'//签名方式
                );
                $get_sign_url = 'https://qyapi.weixin.qq.com/cgi-bin/miniapppay/get_sign?access_token=' . $access_token;
                $response = $client->post($get_sign_url, [
                    'headers' => ['Content-Type' => 'application/json'],
                    'body' => json_encode($parameters)
                ]);
                $paySignData = json_decode($response->getBody(), true);
                if (isset($paySignData['pay_sign']) && $paySignData['pay_sign']) {
                    $parameters['pay_sign'] = $paySignData['pay_sign'];
                    $parameters['package'] = 'prepay_id=' . $parameters['prepay_id'];
                } else {
                    throwError($paySignData['errmsg'] ?? '生成签名错误');
                }
                SetReturnJson($parameters);
            }
        }
        throwError($payData['errmsg'] ?? '调用微信支付错误');
    }

    /**
     * @param $order_refund
     * @return void
     */
    public function doRefund($order_refund)
    {
        $access_token = $this->getAccessToken();
        if (!$access_token) {
            throwError('获取access_token失败');
        }
        $url = 'https://qyapi.weixin.qq.com/cgi-bin/miniapppay/refund?access_token=' . $access_token;
        $refundData = [
            'appid' => $this->appid,//二级商户申请的公众号或移动应用appid
            'mchid' => '1679193843',//二级商户号，由企业微信生成并下发。
            'out_trade_no' => $order_refund['out_trade_no'],
            'out_refund_no' => $order_refund['out_refund_no'],
            'reason' => '用户申请退款',
            'amount' => $order_refund['amount']
        ];
        $client = new Client();
        $response = $client->post($url, [
            'headers' => ['Content-Type' => 'application/json'],
            'body' => json_encode($refundData)
        ]);
        $refundData = json_decode($response->getBody(), true);
        Log::info('refundData:' . json_encode($refundData));
        if (isset($refundData['errcode']) && $refundData['errcode'] == 0) {
            if (isset($refundData['amount']['refund']) && $refundData['amount']['refund']) {
                //调用成功了
                if ($order_refund['model'] == 'refund_order') {
                    $order_refund = OrderRefund::find($order_refund['id']);
                    $order_refund->refund_cash_status = 1;
                    $order_refund->save();
                }
                SetReturnJson([]);
            }
            throwError('不能超过原订单支付金额');
        }
        throwError($refundData['errmsg'] ?? '调用微信支付错误');
    }

    /**获取access_token
     * @return mixed|string
     */
    protected function getAccessToken()
    {
        $accessToken = Redis::get('corp_access_token');
        if ($accessToken) {
            return $accessToken;
        }
        $corpId = $this->corpId;//企业ID
        $corpSecret = $this->corpSecret;//应用的凭证密钥
        $url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=' . $corpId . '&corpsecret=' . $corpSecret;
        $accessData = json_decode(file_get_contents($url), true);
        if (isset($accessData['errcode']) && $accessData['errcode'] == 0) {
            //将access_token存起来
            if (isset($accessData['access_token']) && $accessData['access_token']) {
                Redis::setex('corp_access_token', 3600, $accessData['access_token']);
                return $accessData['access_token'];
            }
        }
        return '';
    }

    //随机字符串(不长于32位)
    private function getNonceStr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
}